package com.chenwenxuan.sync.ui.tree;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import com.chenwenxuan.sync.console.model.TaskCatalog;
import com.chenwenxuan.sync.event.Event;
import com.chenwenxuan.sync.event.EventsManager;
import com.chenwenxuan.sync.event.IEventHandler;
import com.chenwenxuan.sync.event.IEventSource;
import com.chenwenxuan.sync.ui.AbstractAction;
import com.chenwenxuan.sync.ui.MenuManager;
import com.chenwenxuan.sync.ui.tree.desginer._TaskTreePanel;

public class AppNavigation extends _TaskTreePanel 
	implements TreeWillExpandListener, PopupMenuListener, /*IEventSource, */MouseListener {

	private static final long serialVersionUID = -683471175816425409L;
	
	public static final Event FillNavPopMenuEvent = new Event("FillNavPopMenuEvent");
	public static final Event DefaultOpenEditorEvent = new Event("DefaultOpenEditorEvent");
	
	private static final Event [] events = new Event[] {FillNavPopMenuEvent, DefaultOpenEditorEvent};
	
	private TaskTreeService taskTreeService;
	private DefaultTreeModel treeModel;
	private JPopupMenu taskTreePopupMenu;
	private MenuManager menuManager;
	//private EventsManager eventsManager;
	private DoubleClickListener doubleclickListener;
	
	private List<AbstractAction> defaultOpenEditorActions;
	


	/**
	 * Create the panel.
	 */
	public AppNavigation() {
		super();
	}
	
	public DefaultMutableTreeNode getSelectedNode() {
		return JTreeUtilities.toDefaultMutableTreeNode(taskTree.getSelectionPath());
	}
	
	public DefaultMutableTreeNode [] getSelectedNodes() {
		TreePath[] treePaths = taskTree.getSelectionPaths();
		if ( treePaths == null ) 
			return new DefaultMutableTreeNode[0];
		DefaultMutableTreeNode [] nodes = new DefaultMutableTreeNode[treePaths.length];
		for ( int i = 0 ; i < treePaths.length; i++ ) {
			nodes[i] = JTreeUtilities.toDefaultMutableTreeNode(treePaths[i]) ;
		}
		return nodes;
	}
	
	public void init() {
		taskTreePopupMenu =  new JPopupMenu();
		menuManager = new MenuManager(new Event[]{FillNavPopMenuEvent});
		taskTree.setComponentPopupMenu(taskTreePopupMenu);
		
		taskTreePopupMenu.addPopupMenuListener(this);

		TaskTreeNode root = taskTreeService.getRoot();
		
		treeModel = new DefaultTreeModel(root);
		taskTree.setModel(treeModel);
		taskTree.setCellRenderer(new TaskTreeRender());
		taskTree.addTreeWillExpandListener(this);
		taskTree.setRootVisible(false);
		taskTree.setShowsRootHandles(true);
		refresh(root, true);
		
		defaultOpenEditorActions = new ArrayList<AbstractAction>();
		doubleclickListener = new DoubleClickListener();
		
		//eventsManager = new EventsManager(this, events);
		taskTree.addMouseListener(doubleclickListener);
		taskTree.addMouseListener(this);
	}
	
	public void tryInvokeDefaultOpenEditorAction() {
		Object selectedObject = getSelectedNode().getUserObject();
		for ( AbstractAction action : defaultOpenEditorActions ) {
			if ( action.canOpenEditor(selectedObject) ) {
				try {
					action.actionPerformed(null);
				} catch(Exception ee) {}
				return;
			}
		}
	}
	

	public void refresh(DefaultMutableTreeNode parent, boolean forceUpdate) {
		if ( parent.getChildCount() > 0 && !forceUpdate) {
			return;
		}
		
		Object userObject = parent.getUserObject();
		if (! (userObject instanceof TaskCatalog)) {
			return;
		}
		
		parent.removeAllChildren();
		
		TaskTreeNode[] children = taskTreeService.getChildren(parent);
		for ( TreeNode child : children) {
			parent.add((MutableTreeNode)child);
		}
		treeModel.nodeStructureChanged(parent);

	}

	@Override
	public void treeWillExpand(TreeExpansionEvent treeExpansionEvent) throws ExpandVetoException {
		TreePath path = treeExpansionEvent.getPath();
		DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
		refresh(node, true);

	}

	@Override
	public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
		
		menuManager.raiseEvent(FillNavPopMenuEvent, getSelectedNodes());
		menuManager.fullfillPopupMenu(taskTreePopupMenu);

	}
	
	@Override
	public void popupMenuCanceled(PopupMenuEvent e) {
		menuManager.clearPopupMenu(taskTreePopupMenu);
	}

	@Override
	public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
		menuManager.clearPopupMenu(taskTreePopupMenu);
		
	}
	
	@Override
	public void treeWillCollapse(TreeExpansionEvent treeExpansionEvent)
			throws ExpandVetoException { }
	
	
	
	public JTree getTaskTree() {
		return taskTree;
	}

	public TaskTreeService getTaskTreeService() {
		return taskTreeService;
	}

	public void setTaskTreeService(TaskTreeService taskTreeService) {
		this.taskTreeService = taskTreeService;
	}

	public void addDefaultOpenEditorAction(AbstractAction action) {
		defaultOpenEditorActions.add(action);
	}
	
	/*@Override
	public void addEventHandler(IEventHandler target, String event) {
		eventsManager.addEventHandler(target, event);
	}

	@Override
	public void removeEventHandler(IEventHandler target, String event) {
		eventsManager.addEventHandler(target, event);
	}

	@Override
	public String getId() {
		return "TaskTreePanel";
	}*/
	
	public class DoubleClickListener extends MouseAdapter {
		public void mousePressed(MouseEvent e) {
	         int selRow = taskTree.getRowForLocation(e.getX(), e.getY());
	         
	         if(selRow != -1) {
	             if(e.getClickCount() == 1) {
	                 //mySingleClick(selRow, selPath);
	             }
	             else if(e.getClickCount() == 2) {
	            	 taskTree.setSelectionRow(selRow);
	            	 tryInvokeDefaultOpenEditorAction();
	             }
	         }
	     }
	}

	@Override
	public void mouseClicked(MouseEvent e) {}

	@Override
	public void mouseEntered(MouseEvent e) {}

	@Override
	public void mouseExited(MouseEvent e) {}

	@Override
	public void mousePressed(MouseEvent e) {
		if (SwingUtilities.isRightMouseButton(e)) {
			selectNode(e);
		}
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		
		if (SwingUtilities.isRightMouseButton(e)) {
			selectNode(e);
		}
	
			
	}
	
	private void selectNode(MouseEvent e) {
		int x = e.getX();
        int y = e.getY();
        JTree tree = (JTree)e.getSource();
        TreePath path = tree.getPathForLocation(x, y);
        if (path == null)
            return;

        tree.setSelectionPath(path);
	}

	public MenuManager getMenuManager() {
		return menuManager;
	}




}
